<?php
/**
 * excel 管理
 *
 * @author    Alex Xun xunzhibin@expert.com
 * @version   1.0
 * @copyright (C) 2018 Jnexpert Ltd. All rights reserved
 * @file      Excel.php
 */

namespace app\export\controller\v1;

use controller\excel\BasicController;

/**
 * excel 控制器
 *
 * @author Alex Xun xunzhibin@jnexpert.com
 * @package controller
 */
class Excel extends BasicController
{
    /**
     * 单元格
     *
     * @var array
     **/
    public $cells = [
        'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
        'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
        'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
    ];

    /**
     * 开始 行
     *
     * @var int
     */
    public $row = 1;

    /**
     * 行 初始化
     *
     * @author Alex Xun xunzhibin@jnexpert.com
     */
    protected function initRow()
    {
        $this->row = 1;
    }

    /**
     * 创建
     *
     * 生成excel数据，并输出到Web浏览器
     *
     * @author Alex Xun xunzhibin@jnexpert.com
     */
    public function create()
    {
        /*
        $data = [
            'worksheet' => [
                [
                    'tag' => [
                        'name' => '工作表1',
                    ],
                    'list' => '哈哈',
                ],
                [
                    'tag' => [
                        'name' => '工作表2',
                    ],
                    'list' => [
                        '呵呵', '嘿嘿'
                    ]
                ],
                [
                    'style' =>[
                        // 字体颜色
                        'font_color' => '#FFDDEE',
                    ],
                    'is_sheet' => true,
                    'tag' => [
                        'name' => '工作表3',
                    ],
                    // 单元格数据
                    'list' => [
                        [ 1, '寻' ],
                        [ 2, '刘' ],
                    ],
                ],
            ],
            'style' => [
                // 标签颜色
                'tag_color' => '#FF00dd',
                // 默认列宽
                'column_width' => 20,
                // 默认行高
                'row_height' => 30,
                // 字体大小
                'font_size' => 14,
                // 字体颜色
                'font_color' => '#FF0',
                // 粗体
                'is_bold' => true,
                // 字体水平对齐
                'horizontal' => 'center',
                // 字体垂直对齐
                'vertical' => 'center',
            ],
        ];
        */

        if(! isset($this->data['worksheet']) || ! $this->data['worksheet']) {
           throw new \think\exception\ValidateException('Missing param -- [worksheet]');
        }

        // 样式
        $style = isset($this->data['style']) ? $this->data['style'] : [];
        // 设置工作表
        $this->setSheet($this->data['worksheet'], $style);

        $this->export();
    }

    /**
     * 工作表
     *
     * 创建工作表，并设置工作表中数据
     *
     * @author Alex Xun xunzhibin@jnexpert.com
     *
     * @param array $sheet 工作表集合
     * @param array $style 样式集合
     */
    protected function setSheet($sheet, $style)
    {
        // 循环创建
        foreach($sheet as $key => $row) {
            // 样式
            if(isset($row['style'])) {
                $style = array_merge($style, $row['style']);
            }
            // 工作表标签
            $tag = isset($row['tag']) ? $row['tag'] : [];
            // 单元格值
            $data = isset($row['list']) ? $row['list'] : [];
            $data = is_array($data) ? $data : (array)$data;

            // 初始化时，已存在一个工作表，从第二个开始创建
            if($key && isset($row['is_sheet']) && $row['is_sheet']) {
                // 创建
                $this->sheet = $this->spreadsheet->createSheet();
            }

            // 工作表标签
            $this->setTag($tag, $style);

            // 默认值
            $this->setDefault($style);

            // 初始化写入行
            if(isset($row['is_sheet']) && $row['is_sheet']) {
                $this->initRow();
            }

            // 单元格
            if($data) {
                $this->setCell($data, $style);
            }
        }
    }

    /**
     * 工作表标签
     *
     * @author Alex Xun xunzhibin@jnexpert.com
     *
     * @param array $data
     */
    protected function setTag($data, $style)
    {
        // 名称
        if(isset($data['tag_name']) && $data['tag_name']) {
            $this->sheet->setTitle($data['tag_name']);
        }

        // 颜色
        if(isset($style['tag_color']) && $style['tag_color']{0} === '#') {
            $color = ltrim($style['tag_color'], '#');
            $this->sheet->getTabColor()->setRGB($color);
        }
    }

    /**
     * 默认值
     *
     * @author Alex Xun xunzhibin@jnexpert.com
     *
     * @param array $data
     */
    protected function setDefault($style)
    {
        // 默认列宽
        if(isset($style['column_width']) && is_numeric($style['column_width'])) {
            $this->sheet->getDefaultColumnDimension()->setWidth($style['column_width']);
        }

        // 默认行高
        if(isset($style['row_height']) && is_numeric($style['row_height'])) {
            $this->sheet->getDefaultRowDimension()->setRowHeight($style['row_height']);
        }
    }


    /**
     * 单元格
     *
     * 设置单元格值，相关样式
     *
     * @author Alex Xun xunzhibin@jnexpert.com
     *
     * @param array $data 单元格值集合
     * @param array $style 单元格样式集合
     */
    protected function setCell($data, $style)
    {
        // 将指针指向第一个值
        reset($data);
        for($i = 0; $i < count($data); $i++) {
            // 当前指针指向元素
            $value = current($data);
            // 指针向前移动一位
            next($data);

            // 数组
            if(is_array($value)) {
                $this->setCell($value, $style);
                continue;
            }

            // 坐标
            $coordinate = $this->getCellCoordinate($i);
            // var_dump($coordinate);

            // 值
            $this->sheet->setCellValue($coordinate, $value);

            // 字体样式
            $this->setFontStyle($coordinate, $style);
        }

        $this->row++;
    }

    /**
     * 单元格坐标
     *
     * 根据写入单个值的个数，获取对应单元格坐标
     *
     * @author Alex Xun xunzhibin@jnexpert.com
     *
     * @param int $num 第几个
     *
     * @return string
     */
    protected function getCellCoordinate($num)
    {
        // 商
        $quotient = floor($num / count($this->cells)); // 向下取整

        // 余
        $remainder = $num % count($this->cells);

        if($num < count($this->cells)) {
            $coordinate = $this->cells[$remainder] . $this->row;
        } else {
            $coordinate = $this->cells[($quotient - 1)] . $this->cells[$remainder] . $this->row;
        }

        return $coordinate;
    }

    /**
     * 字体样式
     *
     * @author Alex Xun xunzhibin@jnexpert.com
     *
     * @param stirng $coordinate 单元格坐标
     * @param array $style 样式集合
     */
    protected function setFontStyle($coordinate, $style)
    {
        $sheetStyle = $this->sheet->getStyle($coordinate);

        // 大小
        if(isset($style['font_size']) && is_numeric($style['font_size'])) {
            // $this->sheet->getStyle($cell)->getFont()->setSize($style['font_size']);
            $sheetStyle->getFont()->setSize($style['font_size']);
        }

        // 颜色
        if(isset($style['font_color']) && $style['font_color']{0} === '#') {
            $color = ltrim($style['font_color'], '#');
            // $this->sheet->getStyle($cell)->getFont()->getColor()->setARGB($color);
            $sheetStyle->getFont()->getColor()->setARGB($color);
        }

        // 粗体
        if(isset($style['is_bold'])) {
            // $this->sheet->getStyle($cell)->getFont()->setBold((bool)$style['is_bold']);
            $sheetStyle->getFont()->setBold((bool)$style['is_bold']);
        }

        // 水平对齐方式
        if(isset($style['horizontal']) && $style['horizontal']) {
            // $this->sheet()->getStyle($cell)->getAlignment()->applyFromArray([
                // 'horizontal' => $style['horizontal'];
            // ]);
            $sheetStyle->getAlignment()->applyFromArray([
                'horizontal' => $style['horizontal']
            ]);
        }

        // 垂直对齐方式
        if(isset($style['vertical']) && $style['vertical']) {
            // $this->sheet()->getStyle($cell)->getAlignment()->applyFromArray([
                // 'vertical' => $style['vertical'];
            // ]);
            $sheetStyle->getAlignment()->applyFromArray([
                'vertical' => $style['vertical']
            ]);
        }
    }
}
